package com.abcd.godating.repository.mongo;

import java.util.Date;
import java.util.List;

import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import com.abcd.godating.domain.Message;
import com.abcd.godating.service.MessageService;

@Repository
public class MessageRepository implements MessageService {

	@Autowired
	private MongoTemplate mongoTemplate;

	@Override
	public void delete(long who, boolean isFrom, ObjectId... ids) {
		if (isFrom) {
			mongoTemplate.updateMulti(
					Query.query(Criteria.where("_id").in(ids).and("from")
							.is(who)), Update.update("fromDeleted", true),
					Message.class);
		} else {
			mongoTemplate.updateMulti(Query.query(Criteria.where("_id").in(ids)
					.and("to").is(who)), Update.update("toDeleted", true),
					Message.class);
		}

	}

	@Override
	public List<Message> getBetween(long who, long withWho, int skip, int limit) {
		Query query = Query
				.query(Criteria.where("from").is(who).and("to").is(withWho)
						.and("fromDeleted").is(false))
				.or(Query.query(Criteria.where("to").is(who).and("from")
						.is(withWho).and("toDeleted").is(false))).skip(skip)
				.limit(limit);
		return mongoTemplate.find(query, Message.class);
	}

	@Override
	public List<Message> getIncoming(long to, int skip, int limit) {
		Query query = Query
				.query(Criteria.where("to").is(to).and("toDeleted").is(false))
				.skip(skip).limit(limit);
		query.fields().exclude("message");
		return mongoTemplate.find(query, Message.class);
	}

	@Override
	public List<Message> getIncomingUnRead(long to, int skip, int limit) {
		Query query = Query
				.query(Criteria.where("to").is(to).and("read").is(false)
						.and("toDeleted").is(false)).skip(skip).limit(limit);
		query.fields().exclude("message");
		return mongoTemplate.find(query, Message.class);
	}

	@Override
	public List<Message> getOutgoing(long from, int skip, int limit) {
		Query query = Query
				.query(Criteria.where("from").is(from).and("fromDeleted")
						.is(false)).skip(skip).limit(limit);
		query.fields().exclude("message");
		return mongoTemplate.find(query, Message.class);
	}

	@Override
	public boolean hasUnread(long to) {
		Query query = Query.query(Criteria.where("to").is(to).and("toDelete")
				.is(false).and("read").is(true));

		return mongoTemplate.findOne(query, Message.class) != null;
	}

	@Override
	public Message read(ObjectId id, long who, boolean isFrom) {
		if (isFrom) {
			Query query = Query.query(Criteria.where("_id").is(id).and("from")
					.is(who).and("fromDelete").is(false));
			return mongoTemplate.findOne(query, Message.class);
		} else {
			Query query = Query.query(Criteria.where("_id").is(id).and("to")
					.is(who).and("toDelete").is(false));
			Message message = mongoTemplate.findOne(query, Message.class);
			if (!message.isRead()) {
				mongoTemplate.updateFirst(
						query.addCriteria(Criteria.where("read").is(false)),
						Update.update("read", true), Message.class);
			}
			return message;
		}
	}

	@Override
	public Message sent(long from, long to, String content) {
		Message message = new Message();
		message.setFrom(from);
		message.setTo(to);
		message.setDate(new Date());
		message.setContent(content);
		message.setRead(false);
		mongoTemplate.save(message);
		return message;
	}

}
